/*************************************************************************************
 * Nombre del archivo: Generador_Analizador_lexico.java
 * Universidad del Valle de Guatemala
 * Curso: Diseño de Lenguajes de Programación
 * @author martin
 *          Martín Guzmán 08041
 * Fecha: Abril de 2010
 * Descripción: Generador de analizador léxico
*************************************************************************************/

import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Generador_Analizador_Lexico {
    
    LinkedList<String> file_lines = new LinkedList<String>();
    String path_to_save="";
    //--------------------------------------------------------------------------
    //------------ variables para lenguaje de cocol ----------------------------
    String Cocol="";
    String ScannerSpecification="";
    String ParserSpecification="";
    String WhiteSpaceDecl="";
    String SetDecl="";
    String Set="";
    String BasicSet="";
    String Char="";
    String TokenDecl="";
    String TokenExpr="";
    String TokenFactor="";
    String TokenTerm="";
    String Symbol="";
    String Production="";
    String Expression="";
    String Term="";
    String Attributes="";
    String SemAction="";
    String KeywordDecl="";
    String Factor="";
    String ANY="";
    //--------------------------------------------------------------------------

    /***********************************************
     * Método: Generador_Analizador_Lexico
     * Uso: Constructor
    ***********************************************/
    public Generador_Analizador_Lexico(){}

    /***********************************************
     * Método: Generador_Analizador_Lexico
     * Uso: Constructor
     * @param file_lines
     * @param path contiene la carpeta en donde se creará el generador
    ***********************************************/
    public Generador_Analizador_Lexico(String path, LinkedList<String> file_lines){

        this.path_to_save=path;
        this.file_lines.clear();
        this.Agregar_a_lista(file_lines, this.file_lines);
        this.Inicializar_Cocol();
        if(this.Revisar_Sintaxis_Cocol()){
            Main.Print("\n***********************************************************");
            Main.Print("Archivo con sintaxis de Cocol correcta");
            Main.Print("\n***********************************************************\n");
            this.Obtener_Sintaxis();
            this.Generar_Automatas();
            this.Generar_Codigo();
        }
        else{
            Main.Print("\n***********************************************************");
            Main.Print("Archivo de entrada no válido acorde a la sintaxis de Cocol");
            Main.Print("\n***********************************************************");
        }
    }

    /***********************************************
     * Método: Agregar_a_lista
     * Uso: Agrega elementos de la lista fuente a la lista destino
     * @param fuente
     * @param destino
    ***********************************************/
    public void Agregar_a_lista(List fuente, List destino){
        for(int i=0;i<fuente.size();i++){
            destino.add(fuente.get(i));
        }
    }

    /***********************************************
     * Método: Copiar_a_cadena
     * Uso: Agrega a una cadena todas las líneas
     *      a partir del índice ingresado
     * @param a contiene el índice de donde empezar a copiar
    ***********************************************/
    public String Copiar_a_cadena(int a){
        String retorno = "";
        try{
            retorno = this.file_lines.get(a);
        }catch(Exception exp){
            Main.PrintDB("Error al copiar las líneas del archivo a una cadena...");
            return "";
        }
        for(int i=a+1;i<this.file_lines.size();i++){
            retorno+="\n"+this.file_lines.get(i);
        }
        return retorno;

    }

    /***********************************************
     * Método: Revisar_Sintaxis_Cocol
     * Uso: Revisa si lo ingresado hace match con toda la sintaxis de cocol
     * @param file_lines
    ***********************************************/
    public boolean Revisar_Sintaxis_Cocol() {
        //----------------------------------------------
        //copia todo el archivo a una cadena
        String archivo_cadena = this.Copiar_a_cadena(0);
        //----------------------------------------------
        Pattern pattern = Pattern.compile(Cocol);
        Matcher matcher = pattern.matcher(archivo_cadena);
        //----------------------------------------------
        String cadena_encontrada=this.Buscar_Cadena(pattern, matcher);
        //----------------------------------------------
        if(archivo_cadena.compareTo(cadena_encontrada)!=0){
            return false;
        }
        return true;
    }
    
    /***********************************************
     * Método: Inicializar_Cocol
     * Uso: Genera todo el lenguaje reconocido por cocol
    ***********************************************/
    private void Inicializar_Cocol() {
        //##############################################################################################
        //----------------------------------------------------------------------------------------------
            //##################################################################
            // ------- vocabulario de cocol ------------------------------------
            String letter="[a-zA-Z]";
            String digit="\\d";
            String number=digit+"("+digit+")*";
            String ident=letter+"("+letter+"|"+digit+")*";
            String string="\""+"("+number+"|"+letter+"|[^\\s])*"+"\"";
            String character="\'"+"("+number+"|"+letter+"|[^\\s])"+"\'";
            // -----------------------------------------------------------------
            //##################################################################
            // ------- ScannerSpecification ------------------------------------
                // -------------------------------------------------------------
                Char = character+"|(CHR"+"\\("+number+"\\)"+")";
                BasicSet = "("+string+"|"+ident+"|"+"("+Char+")"+"(\\.\\.("+Char+"))?"+")";
                Set = BasicSet+"("+"(\\+|\\-)"+BasicSet+")*";
                SetDecl = "("+ident+"( |\\t)*"+"="+"( |\\t)*"+Set+")";
                // -------------------------------------------------------------
                //##############################################################
                // ------- White Space declaration -----------------------------
                    WhiteSpaceDecl="IGNORE"+"(\\s)*"+Set;
                    ANY="([\\w]"+"|"+"[^\\w])*";
                    Attributes="<\\."+"("+ANY+")"+"\\.>";
                    SemAction="\\(\\."+"("+ANY+")"+"\\.\\)";
                // -------------------------------------------------------------
                // -------------------------------------------------------------
                KeywordDecl=ident+"( |\\t)*"+"="+"( |\\t)*"+string+"\\.";
                // -------------------------------------------------------------
                Symbol = ident+"|"+string+"|"+character;
                /*
                String TokenFactor = "("+Symbol+"|"+"\\(TokenExpr\\)"+"|"+"\\[TokenExpr\\]"+"|"+"\\{TokenExpr\\})";
                String TokenTerm = TokenFactor+"("+TokenFactor+")*";
                String TokenExpr = "(("+TokenTerm+")"+"(\\|("+TokenTerm+"))*)";
                Main.Print("TokenExpr: "+TokenExpr);
                String b = TokenExpr;
                TokenExpr = TokenExpr.replaceAll("TokenExpr",b);
                TokenExpr = TokenExpr.replaceAll("TokenExpr","("+Symbol+")");
                Main.Print("TokenExpr: "+TokenExpr);
                //String TokenExpr = "("+Symbol+"|\\(("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})*(\\|(("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})*))*\\)|\\[("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})*(\\|(("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})*))*\\]|\\{("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})*(\\|(("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})*))*\\})("+Symbol+"|\\(("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})*(\\|(("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})*))*\\)|\\[("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})*(\\|(("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})*))*\\]|\\{("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})*(\\|(("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})*))*\\})*(\\|(("+Symbol+"|\\(("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})*(\\|(("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})*))*\\)|\\[("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})*(\\|(("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})*))*\\]|\\{("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})*(\\|(("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})*))*\\})("+Symbol+"|\\(a\\)|\\[("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})*(\\|(("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})*))*\\]|\\{("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})*(\\|(("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})("+Symbol+"|\\(a\\)|\\[a\\]|\\{a\\})*))*\\})*))*";
                 */
                TokenExpr = "(("+"("+"("+Symbol+"|"+"\\("+"(("+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+")*"+")"+")"+"(\\|("+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+")*"+")"+"))*)"+"\\)"+"|"+"\\["+"(("+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+")*"+")"+")"+"(\\|("+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+")*"+")"+"))*)"+"\\]"+"|"+"\\{"+"(("+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+")*"+")"+")"+"(\\|("+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+")*"+")"+"))*)"+"\\})"+"("+"("+Symbol+"|"+"\\("+"(("+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+")*"+")"+")"+"(\\|("+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+")*"+")"+"))*)"+"\\)"+"|"+"\\["+"(("+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+")*"+")"+")"+"(\\|("+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+")*"+")"+"))*)"+"\\]"+"|"+"\\{"+"(("+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+")*"+")"+")"+"(\\|("+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+")*"+")"+"))*)"+"\\})"+")*"+")"+")"+"(\\|("+"("+"("+Symbol+"|"+"\\("+"(("+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+")*"+")"+")"+"(\\|("+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+")*"+")"+"))*)"+"\\)"+"|"+"\\["+"(("+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+")*"+")"+")"+"(\\|("+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+")*"+")"+"))*)"+"\\]"+"|"+"\\{"+"(("+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+")*"+")"+")"+"(\\|("+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+")*"+")"+"))*)"+"\\})"+"("+"("+Symbol+"|"+"\\("+"(("+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+")*"+")"+")"+"(\\|("+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+")*"+")"+"))*)"+"\\)"+"|"+"\\["+"(("+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+")*"+")"+")"+"(\\|("+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+")*"+")"+"))*)"+"\\]"+"|"+"\\{"+"(("+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+")*"+")"+")"+"(\\|("+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+"("+"("+Symbol+"|"+"\\("+Symbol+"\\)"+"|"+"\\["+Symbol+"\\]"+"|"+"\\{"+Symbol+"\\})"+")*"+")"+"))*)"+"\\})"+")*"+")"+"))*)";
                 //****************************************************************************************************
                TokenDecl=ident+"("+"( |\\t)*"+"="+"( |\\t)*"+TokenExpr+")?"+"(\\s)*"+"("+"EXCEPT KEYWORDS"+")?"+"\\.";

                String ScannerSP1 = "("+"("+"(CHARACTERS)"+"(\\s)*)"+"(("+SetDecl+")(\\s)*)*"+")";
                String ScannerSP2 = "("+"((KEYWORDS)"+"(\\s)*)"+"(("+KeywordDecl+")(\\s)*)*"+")";
                String ScannerSP3 = "("+"("+"(TOKENS)(\\s)*"+")("+TokenDecl+"(\\s)*)*"+")";
                String ScannerSP4 = "("+"("+WhiteSpaceDecl+")*"+")";
                ScannerSpecification= ScannerSP1+ScannerSP2+ScannerSP3+ScannerSP4;
            // -----------------------------------------------------------------
            //##################################################################
            // ------- ParserSpecification -------------------------------------
                Production="";
                Expression="";
                Term="";
                Factor="";

                ParserSpecification="PRODUCTIONS"+"(\\s)*"+"("+Production+"(\\s)*)*";
            // -----------------------------------------------------------------
            //##################################################################
            // ------- Cocol sintax --------------------------------------------
                String Cocol1 = "COMPILER"+"(\\s)*"+ident;
                String Cocol2 = "("+ScannerSpecification+")";
                String Cocol3 = "("+ParserSpecification+")";
                String Cocol4 = "("+"END"+"(\\s)*"+ident+"\\.)";

                Cocol = Cocol1+"(\\s)*"+Cocol2+"(\\s)*"+Cocol3+"(\\s)*"+Cocol4;
                //String Cocol = ("COMPILER"+"(\\s)*"+ident+"("+ScannerSpecification+")"+"(\\s)*"+"("+"END"+ident+"\\.)");
            // -----------------------------------------------------------------
            //##################################################################
        //----------------------------------------------------------------------------------------------
        //##############################################################################################
        //****************************************************************************************************
    }
    
    /***********************************************
     * Método: Obtener_Sintaxis
     * Uso: Entiende el archivo de entrada y lo almacena
    ***********************************************/
    public void Obtener_Sintaxis() {

        String archivo_cadena = this.Copiar_a_cadena(0);
        //--------- obtener ScannerSpecification -------------------------------
        Pattern pattern = Pattern.compile(ScannerSpecification);
        Matcher matcher = pattern.matcher(archivo_cadena);
        String Scanner_spec = this.Buscar_Cadena(pattern,matcher);
        //--------- obtener ParserSpecification --------------------------------
        pattern = Pattern.compile(ParserSpecification);
        matcher = pattern.matcher(archivo_cadena);
        String Parser_spec = this.Buscar_Cadena(pattern,matcher);
        //----------------------------------------------------------------------
        Main.PrintDB("\n***********************************************");
        Main.PrintDB("\nScanner Specification: |"+Scanner_spec+"|");
        Main.PrintDB("\n***********************************************");
        Main.PrintDB("\nParser Specification: |"+Parser_spec+"|");
        Main.PrintDB("\n***********************************************");

            String ScannerSP1 = "("+"("+"(CHARACTERS)"+"(\\s)*)"+"(("+SetDecl+")(\\s)*)*"+")";
            String ScannerSP2 = "("+"((KEYWORDS)"+"(\\s)*)"+"(("+KeywordDecl+")(\\s)*)*"+")";
            String ScannerSP3 = "("+"("+"(TOKENS)(\\s)*"+")("+TokenDecl+"(\\s)*)*"+")";
            String ScannerSP4 = "("+"("+WhiteSpaceDecl+")*"+")";
        //--------- obtener CHARACTERS -----------------------------------------
        pattern = Pattern.compile(ScannerSP1);
        matcher = pattern.matcher(Scanner_spec);
        String CHARACTERS_spec = this.Buscar_Cadena(pattern,matcher);
        //----------------------------------------------------------------------
        //--------- obtener KEYWORDS -------------------------------------------
        pattern = Pattern.compile(ScannerSP2);
        matcher = pattern.matcher(Scanner_spec);
        String KEYWORDS_spec = this.Buscar_Cadena(pattern,matcher);
        //----------------------------------------------------------------------
        //--------- obtener TOKENS ---------------------------------------------
        pattern = Pattern.compile(ScannerSP3);
        matcher = pattern.matcher(Scanner_spec);
        String TOKENS_spec = this.Buscar_Cadena(pattern,matcher);
        //----------------------------------------------------------------------
        Main.PrintDB("\n***********************************************");
        Main.PrintDB("\nCHARACTERS_spec: <"+CHARACTERS_spec+">");
        Main.PrintDB("\n***********************************************");
        Main.PrintDB("\nKEYWORDS_spec: <"+KEYWORDS_spec+">");
        Main.PrintDB("\n***********************************************");
        Main.PrintDB("\nTOKENS_spec: <"+TOKENS_spec+">");
        Main.PrintDB("\n***********************************************");
        //----------------------------------------------------------------------
        //--------- obtener SetDecl --------------------------------------------
        LinkedList<String> Lista_SetDecl = this.Get_Lista_Decl(CHARACTERS_spec, SetDecl);
        //----------------------------------------------------------------------
        //--------- obtener KeyWords -------------------------------------------
        LinkedList<String> Lista_KeyWords = this.Get_Lista_Decl(KEYWORDS_spec, KeywordDecl);
        //----------------------------------------------------------------------
        //--------- obtener TokenDecl ------------------------------------------
        LinkedList<String> Lista_TokenDecl = this.Get_Lista_Decl(TOKENS_spec, TokenDecl);
        //----------------------------------------------------------------------
        Main.PrintDB("\n***********************************************");
        Main.PrintDB("\nSetDecl: "+Lista_SetDecl+"");
        Main.PrintDB("\n***********************************************");
        Main.PrintDB("\nLista_KeyWords: "+Lista_KeyWords+"");
        Main.PrintDB("\n***********************************************");
        Main.PrintDB("\nLista_TokenDecl: "+Lista_TokenDecl+"");
        Main.PrintDB("\n***********************************************");
    }

    /***********************************************
     * Método: Generar_Automatas
     * Uso: Genera los autómatas a partir las especificaciones
    ***********************************************/
    public void Generar_Automatas() {
        
    }

    /***********************************************
     * Método: Generar_Codigo
     * Uso: Genera el código del analizador léxico
    ***********************************************/
    public void Generar_Codigo() {
        
    }

    /***********************************************
     * Método: Buscar_indices
     * Uso: retorna un string con el match que encuentre
     * @param pattern
     * @param matcher
    ***********************************************/
    public String Buscar_Cadena(Pattern pattern, Matcher matcher) {

        String cadena_encontrada="";

        if (matcher.find()) {
            cadena_encontrada=matcher.group();
            //Main.Print("Encontrado: \""+cadena_encontrada+"\"");// entre ["+index_begin+","+index_end+"]");
        }
        if(cadena_encontrada.isEmpty()==true){
            return "";
        }
        if(cadena_encontrada.endsWith("\n")){
            cadena_encontrada = cadena_encontrada.substring(0,cadena_encontrada.length()-1);
        }
        return cadena_encontrada;
    }

    /***********************************************
     * Método: Get_SetDecl
     * Uso: retorna una lista con todo lo encontrado
     *      según la ScannerSpecification
     * @param Scanner_spec contiene una cadena con las ScannerSpecification
    ***********************************************/
    public LinkedList<String> Get_Lista_Decl(String cadena, String regex) {

        LinkedList<String> Lista_Decl = new LinkedList<String>();

        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(cadena);
        while(true){
            String a = this.Buscar_Cadena(pattern,matcher);
            if(a.isEmpty()){
                break;
            }
            Lista_Decl.add(a);
        }

        return Lista_Decl;
    }

}